import cv2
import numpy as np
from PIL import ImageGrab
import numpy as np
import pyautogui

def show_image(image):
    cv2.imshow("temp", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def write_image(image):
    cv2.imwrite("Screenshots/temp.png", image)

# 用于展示那些只有一行的图像
def show_line_image(line_img: np.ndarray, title = "Tiled Image", repeat_times: int = 100, wait = False):
    tiled_img = np.repeat(line_img, 100, axis = 0)
    cv2.imshow(title, tiled_img)
    
    if wait:
        cv2.waitKey(0)
        cv2.destroyAllWindows()

def log2txt(str):
    with open("log.txt", "w", encoding="utf-8") as f:
        f.write(str)


# 对窗体进行截图供其他模块分析
def capture():
    try:
        # 获取窗口的位置和大小
        left, top, right, bottom = 10, 440, 781, 1240
        
        # 截图区域
        print(f"正在截取窗口: 坐标({left},{top}) 尺寸({right - left}, {bottom - top})")
        capture = ImageGrab.grab(bbox=(left, top, right, bottom))
        
        # 保存彩色截图
        color_path = r"Screenshots\screenshot_color.png"
        capture.save(color_path)
        print(f"彩色截图已保存到: {color_path}")

        # 转换为cv2格式
        capture_np = np.array(capture)
        screenshot_color = cv2.cvtColor(capture_np, cv2.COLOR_BGR2RGB)
        screenshot_gray = cv2.cvtColor(capture_np, cv2.COLOR_RGB2GRAY)

        # 保存灰度截图
        gray_path = r"Screenshots\screenshot_gray.png"
        cv2.imwrite(gray_path, screenshot_gray)
        print(f"灰度截图已保存到: {gray_path}")
        
        # 显示截图
        # cv2.imshow("Screenshot", screenshot_color)
        # cv2.waitKey(0) 
        # cv2.destroyAllWindows()

        # 返回截图
        return screenshot_gray, screenshot_color
    
    except Exception as e:
        print(f"截图失败: {e}")

        

# 定义：检测黑线的函数（从后往前）
def find_lines(projection, num_lines, threshold_ratio=0.5):
    """从末尾向前找线条"""
    max_val = np.max(projection)
    threshold = max_val * threshold_ratio  # 比如取一半
    lines = []
    new_line = -9999
    for i in range(len(projection) - 1, -1, -1):  # 从末尾向前
        if projection[i] > threshold:
            if abs(i - new_line) > 10:  # 避免一条线附近连续检测
                lines.append(i)
                new_line = i
            if len(lines) == num_lines:
                break
    lines.sort()  # 最后从小到大排序
    return lines


# 二值化图片并去除边缘影响
def binary_crop(image: np.ndarray):

    h, w = image.shape

    # 二值化
    _, binary = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY)

    #TODO 填充法
    # 定义4个角起点
    corners = [(0, 0), (0, w - 1), (h - 1, 0), (h - 1, w - 1)]
    for y, x in corners:
        # 判断角点是不是白色
        if binary[y, x] == 255:
            # 用floodFill填充
            mask = np.zeros((h + 2, w + 2), np.uint8)  # floodFill的mask比原图大2
            cv2.floodFill(binary, mask, (x, y), 0)  # 将连通的255区域填充为0
    return binary

    #TODO 裁剪法
    # 找到非黑色的坐标范围
    # mask = binary < 100
    # coords = np.column_stack(np.where(mask))
    # y_min, x_min = coords.min(axis=0)
    # y_max, x_max = coords.max(axis=0)
    # return binary[y_min : y_max + 1, x_min : x_max + 1]


nums_library = []
nums_hw_ratio = []

# 识别数字
def recognize_digits(image: np.ndarray, desc = ""):
    global nums_library, nums_hw_ratio

    # 加载数字识别库
    if len(nums_library) == 0:
        try:
            nums_library.append(None) # 没有数字0
            nums_hw_ratio.append(None)

            for i in range(15):
                # 载入库数字图片
                img = cv2.imread(f"Numbers/{i + 1}.png", cv2.IMREAD_GRAYSCALE)
                nums_library.append(img)

                #载入库数字宽高比
                h, w = img.shape[:2]
                nums_hw_ratio.append(h / w)
                # print(f"库数字{i + 1}宽高比：{h / w}")

        except Exception as e:
            print(f"加载数字识别库失败：{e}")

    # 去除数字边缘像素
    coords = cv2.findNonZero(image)
    x, y, w, h = cv2.boundingRect(coords)
    image = image[y:y+h, x:x+w]
    cv2.imwrite(f"debug_image/送检图片.png", image)

    # 宽高比
    h, w = image.shape[:2]
    hw_ratio = h / w

    # 根据宽高比选取可能的数字
    possible = []
    log = ""
    for i in range(1, len(nums_hw_ratio)):
        delta = abs(nums_hw_ratio[i] - hw_ratio)
        log += f"图片宽高比{hw_ratio}  数字{i}宽高比{nums_hw_ratio[i]}  差值{delta}\n"
        if delta < 0.5:
            possible.append(i)

    # 如果只有单个数字 则提前结束
    if len(possible) == 1:
        return possible[0]
    if len(possible) == 0:
        # raise Exception(f"根据宽高比没识别到任何数字 {desc}\n{log}")
        return None
    
    # 简单的像素对比
    most_like_num = 0
    max_similar = 0
    for num in possible:
        # 拉伸库尺寸
        origin = cv2.resize(nums_library[num], (w, h))

        # 比较像素差
        diff = cv2.absdiff(image, origin)
        similarity = 1 - (np.sum(diff) / (w * h * 255))
        
        # 识别为该数字
        if similarity > max_similar:
            most_like_num = num
            max_similar = similarity
    
    return most_like_num

# 识别某行/列数字总和
def get_line_sum(array):
    return sum(array) + (len(array) - 1)

# 模拟鼠标点击
def mouse_click(pos):
    pyautogui.click(pos[0] + 10, pos[1] + 440)